/****************************************************************************
 *
 *  ALi (Shanghai) Corporation, All Rights Reserved. 2005 Copyright (C)
 *
 *  File: win_game_sudoku.c
 *
 *  Description: Sudoku game for Glass UI.
 *
 *  History:
 *  Date            Author  		Version  Comment
 *  ====            ======  		=======  =======
 *  1.  2007.4.28   Sharon Zhang 	0.1.000  Initial
 *
 ****************************************************************************/

#include <sys_config.h>
#include <types.h>
#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <osal/osal.h>
#include <hld/pan/pan_dev.h>

#include <api/libosd/osd_lib.h>

#include "osdobjs_def.h"

#include "string.id"
#include "images.id"
#include "osd_config.h"

#include "copper_common/dev_handle.h"
#include "copper_common/com_api.h"
#include "copper_common/system_data.h"

#include "win_com_popup.h"
#include "win_com_list.h"
#include "win_com.h"

#include "copper_common/menu_api.h"
#include "win_com_menu_define.h"
#include "win_game_com.h"

#include "game_sudoku.h"
#define NEW_GAME_FOCUS

#ifndef SD_UI
#define WIN_GAME_LEFT       74//34//210
#define WIN_GAME_TOP        30//30//70
#ifdef SUPPORT_CAS_A
#define WIN_GAME_WIDTH      886
#else
#define WIN_GAME_WIDTH      866
#endif
#define WIN_GAME_HEIGHT     556

//#define TXT_GAME_LEFT       820
#define TXT_GAME_LEFT       684//820
#define TXT_GAME_TOP        (WIN_GAME_TOP + 40)
#define TXT_GAME_WIDTH      210
#define TXT_GAME_HEIGHT     40

#define TXT_GAME_BTN_TOP    (TXT_GAME_TOP + 80)
#define TXT_GAME_BTN_HEIGHT 40
#define TXT_GAME_BTN_GAP    50

#define TXT_GAME_LBL_TOP    (TXT_GAME_BTN_TOP + 200)
#define TXT_GAME_LBL_HEIGHT 33
#define TXT_GAME_LBL_GAP    90

#define TXT_GAME_VAL_TOP    (TXT_GAME_LBL_TOP + 50)
#define TXT_GAME_VAL_HEIGHT 33
#define TXT_GAME_VAL_GAP    90
#else
#define WIN_GAME_LEFT       17//34//210
#define WIN_GAME_TOP        17//70
#define WIN_GAME_WIDTH      576
#define WIN_GAME_HEIGHT     410//(W_H+TITILE_H)

//#define TXT_GAME_LEFT       820
#define TXT_GAME_LEFT       420//820
#define TXT_GAME_TOP        (WIN_GAME_TOP + 20)
#define TXT_GAME_WIDTH      120
#define TXT_GAME_HEIGHT     24

#define TXT_GAME_BTN_TOP    (TXT_GAME_TOP + 40)
#define TXT_GAME_BTN_HEIGHT 28
#define TXT_GAME_BTN_GAP    32

#define TXT_GAME_LBL_TOP    (TXT_GAME_BTN_TOP + 120)
#define TXT_GAME_LBL_HEIGHT 24
#define TXT_GAME_LBL_GAP    56

#define TXT_GAME_VAL_TOP    (TXT_GAME_LBL_TOP + 28)
#define TXT_GAME_VAL_HEIGHT 24
#define TXT_GAME_VAL_GAP    56

#endif

#define WSTL_TEXT_02        WSTL_BUTTON_01_HD
#define WSTL_GAME_BUTTON_01	WSTL_BUTTON_01_HD
#define WSTL_GAME_BUTTON_02	WSTL_BUTTON_05_HD
#define WSTL_GAME_BUTTON_03	WSTL_BUTTON_04_HD
#define WSTL_GAME_TEXT_01   WSTL_BUTTON_01_HD
#define WSTL_GAME_BG_02     WSTL_GAMEWIN_01_HD

PRESULT (*game_key_proc)(UINT32, UINT8, UINT8);
PRESULT (*game_setup)(POBJECT_HEAD, VEVENT, UINT32, UINT32);
void (*game_start)(void);
void (*game_pre_open)(void);
void (*game_1st_draw)(void);
void (*game_event)(UINT32, UINT32);

/*******************************************************************************
 *  Local functions & variables define
 *******************************************************************************/

static unsigned char level;
static UINT16 str_value[64];

static PRESULT sudoku_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static VACTION sudoku_btn_keymap(POBJECT_HEAD obj, UINT32 key);
static PRESULT sudoku_newgame_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static PRESULT sudoku_replay_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static PRESULT sudoku_solve_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static VACTION sudoku_setup_keymap(POBJECT_HEAD obj, UINT32 key);
static PRESULT sudoku_setup_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static PRESULT sudoku_cancel_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static PRESULT sudoku_state_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);
static VACTION sudoku_con_keymap(POBJECT_HEAD obj, UINT32 key);
static PRESULT sudoku_con_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2);

static void sudoku_replay(void);
static void sudoku_solve(void);

extern CONTAINER game_sudoku_con;
extern TEXT_FIELD sudoku_txt_playarea;
extern TEXT_FIELD sudoku_txt_title;
extern TEXT_FIELD txt_newgame;
extern TEXT_FIELD txt_replay;
extern TEXT_FIELD txt_solve;
extern TEXT_FIELD sudoku_txt_setup;
extern TEXT_FIELD sudoku_txt_cancel;

extern TEXT_FIELD sudoku_txt_level;
extern TEXT_FIELD sudoku_txt_value1;
extern TEXT_FIELD sudoku_line_newgame_up;
extern TEXT_FIELD sudoku_line_newgame;
extern TEXT_FIELD sudoku_line_replay;
extern TEXT_FIELD sudoku_line_solve;
extern TEXT_FIELD sudoku_line_setup;
extern TEXT_FIELD sudoku_line_cancel;

DEF_TEXTFIELD(sudoku_txt_playarea, &game_sudoku_con, NULL, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      6, 0, 0, 0, 0, \
      WIN_GAME_LEFT, WIN_GAME_TOP, 1, 1, \
      WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, \
      NULL, sudoku_callback, \
      C_ALIGN_CENTER, 0, 0, \
      0, NULL);

DEF_TEXTFIELD(sudoku_txt_title, &game_sudoku_con, &txt_newgame/*&sudoku_line_newgame_up*/, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      0, 0, 0, 0, 0, \
      TXT_GAME_LEFT, TXT_GAME_TOP, TXT_GAME_WIDTH, TXT_GAME_HEIGHT, \
      WSTL_TEXT_02, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, \
      NULL, NULL, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      0, NULL);

//LDEF_LINE(&game_sudoku_con,sudoku_line_newgame_up,&txt_newgame,0,0,0,0,0,TXT_GAME_LEFT,TXT_GAME_BTN_TOP-7 ,TXT_GAME_WIDTH,4,0,NULL);

DEF_TEXTFIELD(txt_newgame, &game_sudoku_con, &txt_replay/*&sudoku_line_newgame*/, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      1, 1, 1, 5, 2, \
      TXT_GAME_LEFT, TXT_GAME_BTN_TOP + TXT_GAME_BTN_GAP * 0, TXT_GAME_WIDTH, TXT_GAME_BTN_HEIGHT, \
      WSTL_GAME_BUTTON_01, WSTL_GAME_BUTTON_02, WSTL_NOSHOW_IDX, WSTL_GAME_BUTTON_01, \
      sudoku_btn_keymap, sudoku_newgame_callback, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      RS_GAME_NEW_GAME, NULL);

//LDEF_LINE(&game_sudoku_con,sudoku_line_newgame,&txt_replay,0,0,0,0,0,TXT_GAME_LEFT,TXT_GAME_BTN_TOP+TXT_GAME_BTN_HEIGHT+3 ,TXT_GAME_WIDTH,4,0,NULL);

DEF_TEXTFIELD(txt_replay, &game_sudoku_con, &txt_solve/*&sudoku_line_replay*/, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      2, 2, 2, 1, 3, \
      TXT_GAME_LEFT, TXT_GAME_BTN_TOP + TXT_GAME_BTN_GAP * 1, TXT_GAME_WIDTH, TXT_GAME_BTN_HEIGHT, \
      WSTL_GAME_BUTTON_01, WSTL_GAME_BUTTON_02, WSTL_NOSHOW_IDX, WSTL_GAME_BUTTON_01, \
      sudoku_btn_keymap, sudoku_replay_callback, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      RS_GAME_REPLAY, NULL);

//LDEF_LINE(&game_sudoku_con,sudoku_line_replay,&txt_solve,0,0,0,0,0,TXT_GAME_LEFT,TXT_GAME_BTN_TOP+TXT_GAME_BTN_GAP +TXT_GAME_BTN_HEIGHT+3 ,TXT_GAME_WIDTH,4,0,NULL);

DEF_TEXTFIELD(txt_solve, &game_sudoku_con, &sudoku_txt_setup/*&sudoku_line_solve*/, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      3, 3, 3, 2, 4, \
      TXT_GAME_LEFT, TXT_GAME_BTN_TOP + TXT_GAME_BTN_GAP * 2, TXT_GAME_WIDTH, TXT_GAME_BTN_HEIGHT, \
      WSTL_GAME_BUTTON_01, WSTL_GAME_BUTTON_02, WSTL_NOSHOW_IDX, WSTL_GAME_BUTTON_01, \
      sudoku_btn_keymap, sudoku_solve_callback, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      RS_GAME_SOLVE, NULL);

//LDEF_LINE(&game_sudoku_con,sudoku_line_solve,&sudoku_txt_setup,0,0,0,0,0,TXT_GAME_LEFT,TXT_GAME_BTN_TOP+TXT_GAME_BTN_GAP*2+TXT_GAME_BTN_HEIGHT+3 ,TXT_GAME_WIDTH,4,0,NULL);

DEF_TEXTFIELD(sudoku_txt_setup, &game_sudoku_con, &sudoku_txt_cancel/*&sudoku_line_setup*/, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      4, 4, 4, 3, 5, \
      TXT_GAME_LEFT, TXT_GAME_BTN_TOP + TXT_GAME_BTN_GAP * 3, TXT_GAME_WIDTH, TXT_GAME_BTN_HEIGHT, \
      WSTL_GAME_BUTTON_01, WSTL_GAME_BUTTON_03, WSTL_NOSHOW_IDX, WSTL_GAME_BUTTON_01, \
      sudoku_setup_keymap, sudoku_setup_callback, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      RS_GAME_SETUP, NULL);

//LDEF_LINE(&game_sudoku_con,sudoku_line_setup,&sudoku_txt_cancel,0,0,0,0,0,TXT_GAME_LEFT,TXT_GAME_BTN_TOP+TXT_GAME_BTN_GAP*3+TXT_GAME_BTN_HEIGHT+3 ,TXT_GAME_WIDTH,4,0,NULL);

DEF_TEXTFIELD(sudoku_txt_cancel, &game_sudoku_con, &sudoku_txt_level/*&sudoku_line_cancel*/, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      5, 5, 5, 4, 1, \
      TXT_GAME_LEFT, TXT_GAME_BTN_TOP + TXT_GAME_BTN_GAP * 4, TXT_GAME_WIDTH, TXT_GAME_BTN_HEIGHT, \
      WSTL_GAME_BUTTON_01, WSTL_GAME_BUTTON_02, WSTL_NOSHOW_IDX, WSTL_GAME_BUTTON_01, \
      sudoku_btn_keymap, sudoku_cancel_callback, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      RS_COMMON_CANCEL, NULL);

//LDEF_LINE(&game_sudoku_con,sudoku_line_cancel,&sudoku_txt_level,0,0,0,0,0,TXT_GAME_LEFT,TXT_GAME_BTN_TOP+TXT_GAME_BTN_GAP*4+TXT_GAME_BTN_HEIGHT+3 ,TXT_GAME_WIDTH,4,0,NULL);

DEF_TEXTFIELD(sudoku_txt_level, &game_sudoku_con, &sudoku_txt_value1, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      0, 0, 0, 0, 0, \
      TXT_GAME_LEFT, TXT_GAME_LBL_TOP + TXT_GAME_LBL_GAP * 1, TXT_GAME_WIDTH, TXT_GAME_LBL_HEIGHT, \
      WSTL_GAME_TEXT_01, WSTL_GAME_TEXT_01, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, \
      NULL, NULL, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      0, NULL);
DEF_TEXTFIELD(sudoku_txt_value1, &game_sudoku_con, &sudoku_txt_playarea, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      31, 0, 0, 0, 0, \
      TXT_GAME_LEFT, TXT_GAME_VAL_TOP + TXT_GAME_VAL_GAP * 1, TXT_GAME_WIDTH, TXT_GAME_VAL_HEIGHT, \
      WSTL_GAME_TEXT_01, WSTL_GAME_TEXT_01, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, \
      NULL, sudoku_state_callback, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      0, NULL);


DEF_CONTAINER(game_sudoku_con, NULL, NULL, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      0, 0, 0, 0, 0, \
      WIN_GAME_LEFT, WIN_GAME_TOP, WIN_GAME_WIDTH, WIN_GAME_HEIGHT, \
      WSTL_GAME_BG_02, WSTL_GAME_BG_02, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, \
      sudoku_con_keymap, sudoku_con_callback, \
      &sudoku_txt_title, 6, 0);


/*******************************************************************************
 *  Game function
 *******************************************************************************/
void sudoku_setup_game_panel(UINT16 tit_id, UINT16 lev_id)
{
    OSD_SetTextFieldContent(&sudoku_txt_title, STRING_ID, tit_id);
    OSD_SetTextFieldContent(&sudoku_txt_level, STRING_ID, lev_id);
}

void sudoku_update_status(unsigned int value1)
{
	ID vscr_id;
	lpVSCR apVscr;
	
	level = value1;
	OSD_DrawObject((POBJECT_HEAD)&sudoku_txt_value1, C_UPDATE_ALL | C_DRAW_SIGN_EVN_FLG);
	
	vscr_id = osal_task_get_current_id();
	apVscr = OSD_GetTaskVscr(vscr_id);
	OSD_UpdateVscr(apVscr);
}

static PRESULT sudoku_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    UINT32 vkey;
    UINT8 key_repeat_cnt;
    UINT8 key_status;
    PRESULT ret = PROC_PASS;

    switch (event)
    {
    case EVN_UNKNOWNKEY_GOT:
        ret = PROC_LOOP;
		msg_code_to_key_count(param1, &key_repeat_cnt);
		msg_code_to_key_state(param1, &key_status);
        ap_hk_to_vk(0, param1, &vkey);

        ret = game_key_proc(vkey, key_repeat_cnt, key_status);
        break;
    }

    return ret;
}

static VACTION sudoku_btn_keymap(POBJECT_HEAD obj, UINT32 key)
{
    VACTION act = VACT_PASS;

    switch (key)
    {
    case V_KEY_ENTER:
        act = VACT_ENTER;
        break;
    }

    return act;
}

static PRESULT sudoku_newgame_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    UINT8   unact;

    switch (event)
    {
    case EVN_UNKNOWN_ACTION:
        unact = (VACTION)(param1>>16);
        if (unact == VACT_ENTER)
        {
			OSD_SetAttr((POBJECT_HEAD)obj, C_ATTR_INACTIVE);
            OSD_ChangeFocus((POBJECT_HEAD)&game_sudoku_con, 6, \
                  C_UPDATE_FOCUS | C_DRAW_SIGN_EVN_FLG);

            game_start();
        }
        break;
    }

    return ret;
}

static PRESULT sudoku_replay_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    UINT8   unact;

    switch (event)
    {
    case EVN_UNKNOWN_ACTION:
        unact = (VACTION)(param1>>16);
        if (unact == VACT_ENTER)
        {
//			OSD_SetAttr((POBJECT_HEAD)obj, C_ATTR_INACTIVE);
            OSD_ChangeFocus((POBJECT_HEAD)&game_sudoku_con, 6, \
                  C_UPDATE_FOCUS | C_DRAW_SIGN_EVN_FLG);

            sudoku_replay();
        }
        break;
    }

    return ret;
}

static PRESULT sudoku_solve_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    UINT8   unact;

    switch (event)
    {
    case EVN_UNKNOWN_ACTION:
        unact = (VACTION)(param1>>16);
        if (unact == VACT_ENTER)
        {
            sudoku_solve();
        }
        break;
    }

    return ret;
}

static VACTION sudoku_setup_keymap(POBJECT_HEAD obj, UINT32 key)
{
    VACTION act = VACT_PASS;

    switch (key)
    {
    case V_KEY_LEFT:
        act = VACT_DECREASE;
        break;
    case V_KEY_ENTER:
    case V_KEY_RIGHT:
        act = VACT_INCREASE;
        break;
    }

    return act;
}

static PRESULT sudoku_setup_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    return game_setup(obj, event, param1, param2);
}

static PRESULT sudoku_cancel_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    UINT8   unact;

    switch (event)
    {
    case EVN_UNKNOWN_ACTION:
        unact = (VACTION)(param1>>16);
        if(unact == VACT_ENTER)
        {
            ret = PROC_LEAVE;
        }
        break;
    }

    return ret;
}

static PRESULT sudoku_state_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    unsigned char ascstr[6];
    PRESULT ret = PROC_PASS;

    switch (event)
    {
    case EVN_PRE_DRAW:
        switch (obj->bID)
        {
        case 31:
            sprintf(ascstr, "%d", level);
            break;
        }
        ComAscStr2Uni(ascstr, str_value);
        OSD_SetTextFieldStrPoint((PTEXT_FIELD)obj, str_value);
    }

    return ret;
}

static VACTION sudoku_con_keymap(POBJECT_HEAD obj, UINT32 key)
{
    VACTION act;

    switch (key)
    {
    case V_KEY_MENU:
    case V_KEY_EXIT:
        act = VACT_CLOSE;
        break;

    default:
        act = OSD_ContainerKeyMap(obj, key);
    }

    return act;
}

extern CONTAINER    g_win_mainmenu;
static PRESULT sudoku_con_callback(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;

    switch (event)
    {
    case EVN_PRE_OPEN:
	#ifdef NEW_GAME_FOCUS
        OSD_SetAttr((POBJECT_HEAD)&txt_newgame, C_ATTR_ACTIVE);
		OSD_ChangeFocus((POBJECT_HEAD)&game_sudoku_con, 1, \
			C_UPDATE_FOCUS | C_DRAW_SIGN_EVN_FLG);
	#else
        OSD_SetAttr((POBJECT_HEAD)&txt_newgame, C_ATTR_INACTIVE);
		OSD_ChangeFocus((POBJECT_HEAD)&game_sudoku_con, 6, \
			C_UPDATE_FOCUS | C_DRAW_SIGN_EVN_FLG);
	#endif
        game_pre_open();
        break;

    case EVN_POST_CLOSE:
		OSD_DrawObject((POBJECT_HEAD)&g_win_mainmenu, C_DRAW_SIGN_EVN_FLG | C_UPDATE_ALL);
        break;

    case EVN_POST_DRAW:
        game_1st_draw();
        break;

    case EVN_MSG_GOT:
        game_event(param1, param2);
        break;
    }
    return ret;
}

///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
#ifndef SD_UI
#define GAME_MSG_LEFT       165
#define GAME_MSG_TOP        132
#define GAME_MSG_WIDTH      320//250
#define GAME_MSG_HEIGHT     130


#define BOARD_COLS 9
#define BOARD_ROWS 9

#define GRID_WIDTH  53

#define BK_WIDTH  (BOARD_COLS) * GRID_WIDTH
#define BK_HEIGHT (BOARD_ROWS) * GRID_WIDTH

#define BK_X_OFFSET 124//260
#define BK_Y_OFFSET 65//105
#else
#define GAME_MSG_LEFT       165
#define GAME_MSG_TOP        132
#define GAME_MSG_WIDTH      250//250
#define GAME_MSG_HEIGHT     130


#define BOARD_COLS 9
#define BOARD_ROWS 9

#define GRID_WIDTH  30

#define BK_WIDTH  (BOARD_COLS) * GRID_WIDTH
#define BK_HEIGHT (BOARD_ROWS) * GRID_WIDTH

#define BK_X_OFFSET 65//260
#define BK_Y_OFFSET 55//105

#endif

//#define WSTL_GAME_LINE_IDX        0xc1a44c
//#define WSTL_GAME_CURSOR_IDX      0xDE6918
//#define WSTL_GAME_BACKGROUND_IDX  0xbcdbeb
#define WSTL_GAME_BG_01    WSTL_TEXT_04_HD
#define WSTL_GAME_BG_FIX   WSTL_GAMESUDOKU_FIX_HD

static UINT8 Sudoku_Class = 1;
static INT16    cur_col, cur_row;
static UINT8 temp[81];

extern TEXT_FIELD txt_Grid;

DEF_TEXTFIELD(txt_Grid, NULL, NULL, C_ATTR_ACTIVE, C_FONT_DEFAULT, \
      0, 0, 0, 0, 0, \
      BK_X_OFFSET, BK_Y_OFFSET, GRID_WIDTH-2, GRID_WIDTH-2, \
      WSTL_BUTTON_01_FG_HD, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, WSTL_NOSHOW_IDX, \
      NULL, NULL, \
      C_ALIGN_CENTER | C_ALIGN_VCENTER, 0, 0, \
      0, display_strs[0]);

//*******************************************************************************

static void sudoku_draw_cursor(UINT8 row, UINT8 col)
{
	UINT8 pos;
	UINT8 WStyle;
	OSD_Draw_Recode_Ge_Cmd_Start();
	pos = row*BOARD_COLS+col;
	WStyle = WSTL_GAMESUDOKU_CURSOR_HD;
    
	//line width = 2
	drawSquare(BK_X_OFFSET+col*GRID_WIDTH, BK_Y_OFFSET+row*GRID_WIDTH,\
							GRID_WIDTH+2, GRID_WIDTH+2, WStyle);
	if(pboard[pos]!=' ')
	{
		OSD_MoveObject((POBJECT_HEAD)&txt_Grid,BK_X_OFFSET+col*GRID_WIDTH+2,BK_Y_OFFSET+row*GRID_WIDTH+2,FALSE);
		OSD_SetTextFieldContent(&txt_Grid,STRING_NUMBER, (UINT32)(pboard[pos]-'0'));
		OSD_DrawObject((POBJECT_HEAD)&txt_Grid,C_UPDATE_ALL);
	}
    OSD_Draw_Recode_Ge_Cmd_Stop();
}

static void sudoku_draw_grid(UINT8 row, UINT8 col)
{
	UINT8 pos;
	UINT8 WStyle;
	OSD_Draw_Recode_Ge_Cmd_Start();
	pos = row*BOARD_COLS+col;
	if(IS_FIXED(pos))
		WStyle = WSTL_GAME_BG_FIX;
	else
		if((row%6<3&&col%6<3)||(row%6>=3&&col%6>=3))
			WStyle = WSTL_GAMESUDOKU_NORMAL1_HD;
		else
			WStyle = WSTL_GAMESUDOKU_NORMAL2_HD;

	//line width = 2
	drawSquare(BK_X_OFFSET+col*GRID_WIDTH, BK_Y_OFFSET+row*GRID_WIDTH, GRID_WIDTH+2, GRID_WIDTH+2, WStyle);
	
	if(pboard[pos]!=' ')
	{
		OSD_MoveObject((POBJECT_HEAD)&txt_Grid,BK_X_OFFSET+col*GRID_WIDTH+2,BK_Y_OFFSET+row*GRID_WIDTH+2,FALSE);
		OSD_SetTextFieldContent(&txt_Grid,STRING_NUMBER, (UINT32)(pboard[pos]-'0'));
		OSD_DrawObject((POBJECT_HEAD)&txt_Grid,C_UPDATE_ALL);
	}
    OSD_Draw_Recode_Ge_Cmd_Stop();
}

static void sudoku_draw_board(void)
{
    UINT8 i, j;
    OSD_Draw_Recode_Ge_Cmd_Start();
    drawSquare(BK_X_OFFSET, BK_Y_OFFSET, GRID_WIDTH*BOARD_COLS, GRID_WIDTH*BOARD_ROWS, WSTL_GAME_BG_01);
/*
    OSD_DrawVerLine(BK_X_OFFSET-2, BK_Y_OFFSET-3, BOARD_ROWS * GRID_WIDTH+6, \
              		WSTL_GAME_LINE_IDX, NULL);
    OSD_DrawVerLine(BK_X_OFFSET-3, BK_Y_OFFSET-3, BOARD_ROWS * GRID_WIDTH+6, \
              		WSTL_GAME_LINE_IDX, NULL);
	OSD_DrawVerLine(BK_X_OFFSET+BOARD_COLS* GRID_WIDTH+2, BK_Y_OFFSET-3, BOARD_ROWS * GRID_WIDTH+6, \
              		WSTL_GAME_LINE_IDX, NULL);
	OSD_DrawVerLine(BK_X_OFFSET+BOARD_COLS * GRID_WIDTH+1, BK_Y_OFFSET-3, BOARD_ROWS * GRID_WIDTH+6, \
              		WSTL_GAME_LINE_IDX, NULL);

    OSD_DrawHorLine(BK_X_OFFSET-3, BK_Y_OFFSET-2, BOARD_COLS * GRID_WIDTH+6, \
					WSTL_GAME_LINE_IDX, NULL);
    OSD_DrawHorLine(BK_X_OFFSET-3, BK_Y_OFFSET-3, BOARD_COLS * GRID_WIDTH+6, \
					WSTL_GAME_LINE_IDX, NULL);
    OSD_DrawHorLine(BK_X_OFFSET-3, BK_Y_OFFSET+BOARD_ROWS* GRID_WIDTH+1, BOARD_COLS * GRID_WIDTH+6, \
					WSTL_GAME_LINE_IDX, NULL);
    OSD_DrawHorLine(BK_X_OFFSET-3, BK_Y_OFFSET+BOARD_ROWS * GRID_WIDTH+1, BOARD_COLS * GRID_WIDTH+6, \
					WSTL_GAME_LINE_IDX, NULL);
*/
    for (i = 0; i < BOARD_ROWS; i++)
    {
        for(j = 0; j < BOARD_COLS; j++)
        {
			sudoku_draw_grid(i,j);
        }
    }
    OSD_Draw_Recode_Ge_Cmd_Stop();
}

static void sudoku_init(void)
{

    Sudoku_Class = 1;
    cur_col = 0;
    cur_row = 0;
 	
	do{
		load_board();
	}while(Sudoku_Class!=game_class+1);
}

static PRESULT sudoku_key_proc(UINT32 vkey, UINT8 key_repeat_cnt, UINT8 key_status)
{
	PRESULT ret = PROC_LOOP;
	UINT8   back_saved;
	UINT8	pos;
	UINT8 i;
	if (key_status == PAN_KEY_PRESSED)
	{
		switch (vkey)
		{
			case V_KEY_UP:
			case V_KEY_DOWN:
			case V_KEY_LEFT: 
			case V_KEY_RIGHT: 
				sudoku_draw_grid(cur_row, cur_col);
				if (vkey == V_KEY_UP)
				{
				cur_row = cur_row == 0 ? 8 : cur_row - 1;
				}
				else if (vkey == V_KEY_DOWN)
				{
				cur_row = cur_row == 8 ? 0 : cur_row + 1;
				}
				else if (vkey == V_KEY_LEFT)
				{
				cur_col = cur_col == 0 ? 8 : cur_col - 1;
				}
				else if (vkey == V_KEY_RIGHT)
				{
				cur_col = cur_col == 8 ? 0 : cur_col + 1;
				}
				sudoku_draw_cursor(cur_row, cur_col);
				break;

			case V_KEY_0:
				pos = cur_row*BOARD_COLS+cur_col;
				if(!IS_FIXED(pos))
				{
					if(pboard[pos]!=' ')
					{
						pboard[pos]=' ';
    					sudoku_draw_cursor(cur_row, cur_col);
					}
				}
				break;
				
			case V_KEY_1:	case V_KEY_2:	case V_KEY_3:
			case V_KEY_4:	case V_KEY_5:	case V_KEY_6:	case V_KEY_7:
			case V_KEY_8:	case V_KEY_9:
				pos = cur_row*BOARD_COLS+cur_col;
				if(!IS_FIXED(pos))
				{
					pboard[pos]=(vkey-V_KEY_0)+0x30;
    				sudoku_draw_cursor(cur_row, cur_col);
				}
				for (i=0;i<81 ;i++ )
					if(pboard[i]==' ')
						break;
				if(i==81)
				{
					for (i=0;i<81 ;i++ )
						if(pboard[i]!=(GET_DIGIT(solved_board[i])+0x30))
							break;
				}
	
				if(i==81)
				{
					completed=1;
					win_compopup_init(WIN_POPUP_TYPE_OK);
					win_compopup_set_frame(GAME_MSG_LEFT,   GAME_MSG_TOP, GAME_MSG_WIDTH,GAME_MSG_HEIGHT);
					win_compopup_set_msg(NULL, NULL, RS_GAME_YOU_WIN);
					if (win_compopup_open_ext(&back_saved) == WIN_POP_CHOICE_YES)
					{
                        sudoku_draw_board();
						//sudoku_draw_grid(cur_row, cur_col);
						OSD_SetAttr((POBJECT_HEAD)&txt_newgame, C_ATTR_ACTIVE);
						OSD_ChangeFocus((POBJECT_HEAD)&game_sudoku_con, 1, \
						C_UPDATE_FOCUS | C_DRAW_SIGN_EVN_FLG);
					}
				}
				break;
			case V_KEY_MENU:
			case V_KEY_EXIT:
				win_compopup_init(WIN_POPUP_TYPE_OKNO);
				win_compopup_set_frame(GAME_MSG_LEFT,   GAME_MSG_TOP, GAME_MSG_WIDTH,GAME_MSG_HEIGHT);
				win_compopup_set_msg(NULL, NULL, RS_GAME_MSG_DO_YOU_QUIT);
				if (win_compopup_open_ext(&back_saved) == WIN_POP_CHOICE_YES)
				{
                    sudoku_draw_board();
					//sudoku_draw_grid(cur_row, cur_col);
					OSD_SetAttr((POBJECT_HEAD)&txt_newgame, C_ATTR_ACTIVE);
					OSD_ChangeFocus((POBJECT_HEAD)&game_sudoku_con, 1, \
					C_UPDATE_FOCUS | C_DRAW_SIGN_EVN_FLG);
				}
                else
                {
                    sudoku_draw_board();
					sudoku_draw_cursor(cur_row, cur_col);
                }
				break;
			default :
				ret = PROC_PASS;
				break;
		}
	}

	return ret;
}

static void sudoku_start(void)
{
	do{
		load_board();
	}while(Sudoku_Class!=game_class+1);

    sudoku_draw_board();

	cur_row = 0;
	cur_col = 0;
	sudoku_draw_cursor(cur_row, cur_col);
}

static void sudoku_replay(void)
{
	completed=0;
	reset_board();
    sudoku_draw_board();

	cur_row = 0;
	cur_col = 0;
	sudoku_draw_cursor(cur_row, cur_col);
}

static void sudoku_solve(void)
{
	completed=1;
	solve_board();
    sudoku_draw_board();
}

static PRESULT sudoku_setup(POBJECT_HEAD obj, VEVENT event, UINT32 param1, UINT32 param2)
{
    PRESULT ret = PROC_PASS;
    UINT8   unact;

    switch (event)
    {
    case EVN_KEY_GOT:
        unact = (VACTION)(param1>>16);
        switch (unact)
        {
            case VACT_DECREASE:
                Sudoku_Class = Sudoku_Class == 1 ? 3 : Sudoku_Class - 1;
                break;
            case VACT_INCREASE:
                Sudoku_Class = Sudoku_Class == 3 ? 1 : Sudoku_Class + 1;
                break;
        }
    	sudoku_update_status(Sudoku_Class);
        break;
    }

    return ret;
}

static void sudoku_pre_open(void)
{
    sudoku_setup_game_panel(RS_GAME_SUDOKU, RS_GAME_CLASS);

    sudoku_init();     
	sudoku_update_status(Sudoku_Class);
}


static void sudoku_1st_draw(void)
{
    sudoku_draw_board();
#ifndef NEW_GAME_FOCUS
	sudoku_draw_cursor(cur_row, cur_col);
#endif
}


static void sudoku_event(UINT32 param1, UINT32 param2)
{
}


void game_sudoku_init(void)
{
    game_key_proc = sudoku_key_proc;
    game_setup = sudoku_setup;
    game_start = sudoku_start;
    game_pre_open = sudoku_pre_open;
    game_1st_draw = sudoku_1st_draw;
    game_event = sudoku_event;
}

